desc:Alterates all notes according to held notes

slider1:low_note=0<0,11,1{C,Cis,D,Dis,E,F,Fis,G,Gis,A,Ais,B}>Lowest Note for detection
slider2:low_octave=0<-1,9,1>Lowest Octave
slider3:hi_note=0<0,11,1{C,Cis,D,Dis,E,F,Fis,G,Gis,A,Ais,B}>Hightest Note for detection
slider4:hi_octave=1<-1,9,1>Hightest Octave
slider5:mode=1<0,1,1{Filter,Alterate}>Mode (filter for pressed notes or alterate to them)

@init
  function get_hi_note()(
    hi_note + (hi_octave+1)*12
  );
  function get_low_note()(
    low_note + (low_octave+1)*12
  );
  function is_note_on(msg1, velocity)(
    msg1 >= 0x90 && msg1 < 0xa0 && velocity != 0
  );
  function is_note_off(msg1, velocity)(
    (msg1 >= $x90 && msg1 <$xa0 && velocity == 0) ||
    (msg1 >= $x80 && msg1 <$x90)
  );
  function is_in_diapason(note)(
    note >= get_low_note() && note <= get_hi_note()
  );
  notes = 10000;
  function clear_notes() local(i)(
    i = 0;
    while (i < get_hi_note()-get_low_note())(
      notes[i] = 0;
      i += 1;
    )
  );
  function hold_note(note)(
    notes[note-get_low_note()] = 1;
  );
  function release_note(note)(
    notes[note-get_low_note()] = 0;
  );
  function remove_octave(note)(
    note % 12
  );
  function alterate_note(note) local(i, shift, diff, diff2) (
    shift = 127;
    i = 0;
    while (i< get_hi_note()-get_low_note()+1)(
      notes[i] > 0 ? (
         remove_octave(note) == remove_octave(i + get_low_note()) ? (
          shift = 0;
          i = 127;
        ) : (
          diff =  remove_octave(note) - remove_octave(i + get_low_note());
          diff2 = remove_octave(i + get_low_note()) - remove_octave(note);
          abs(diff2) < abs(diff) ? (
            diff = diff2;
          );
          abs(diff) < abs(shift)?(
            shift = diff;
          )
        );
      );
      i+=1;
    );
    shift == 127 ? shift = 0;
    
    note - shift
  );
  function filter_note(note) local(i, filter)(
    i = 0;
    filter = 1;
    while (i < get_hi_note() - get_low_note()+1)(
      notes[i] > 0 ? (
        remove_octave(note) == remove_octave(i + get_low_note()) ? (
          filter = 0;
        );
      );
      i+=1;
    );
    filter
  );

@slider
  clear_notes();

@block
  while (midirecv(offset,msg1,msg2,msg3)) (
    is_note_on(msg1, msg3) ? (
      is_in_diapason(msg2) ? (
        hold_note(msg2);
      ) : (
        mode == 1?(
          msg2 = alterate_note(msg2);
          midisend(offset, msg1, msg2, msg3);
        ) : (
          filter_note(msg2) == 0 ?(
            midisend(offset, msg1, msg2, msg3);
          );
        )
      )
    );
    is_note_off(msg1, msg3) ? (
      is_in_diapason(msg2) ? (
        release_note(msg2);
      ) : (
        mode == 1?(
          msg2 = alterate_note(msg2);
          midisend(offset, msg1, msg2, msg3);
        ) : (
          filter_note(msg2) == 0 ?(
            midisend(offset, msg1, msg2, msg3);
          );
        )
      )
    );
  )

